package com.atguigu.gmall.cart.service.impl;

import com.atguigu.gmall.cart.service.CartService;
import com.atguigu.gmall.common.constant.RedisConst;
import com.atguigu.gmall.common.util.DateUtil;
import com.atguigu.gmall.model.cart.CartInfo;
import com.atguigu.gmall.model.product.SkuInfo;
import com.atguigu.gmall.product.client.ProductFeignClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Collectors;

/**
 * @author atguigu-mqx
 */
@Service
public class CartServiceImpl implements CartService {
    //  需要依赖product
    @Autowired
    private ProductFeignClient productFeignClient;

    @Autowired
    private RedisTemplate redisTemplate;


    @Override
    public void addToCart(Long skuId, String userId, Integer skuNum) {
        /*
        1.  判断当前这个skuId 在购物车中是否存在！
                true:
                    存在 数量相加
                false:
                    不存在 直接插入缓存

         2.  添加有放入购物车价格，实时价格！

         3.  每次添加的时候都是默认选中状态！

         4.  苏宁：展示的时候需要按照添加时间排序，京东：修改时间排序！
         */

        //  购物车数据存在在缓存：需要获取到购物车数据！ 缓存使用哪种数据类型来存储购物车！ hash hset key field value hget key field
        //  key = user:userId:cart field = skuId  value = cartInfo;
        String cartKey = this.getCartKey(userId);

        //  hget key field
        CartInfo cartInfoExist = (CartInfo) this.redisTemplate.opsForHash().get(cartKey, skuId.toString());

        //  判断
        if (cartInfoExist != null) {
            //  商品存在
            cartInfoExist.setSkuNum(cartInfoExist.getSkuNum() + skuNum);
            //  赋值实时价格
            cartInfoExist.setSkuPrice(productFeignClient.getSkuPrice(skuId));
            //  选中状态
            if (cartInfoExist.getIsChecked().intValue() == 0) {
                cartInfoExist.setIsChecked(1);
            }
            //  赋值修改时间
            cartInfoExist.setUpdateTime(new Date());

        } else {
            SkuInfo skuInfo = productFeignClient.getSkuInfo(skuId);
            //  创建一个cartInfo
            cartInfoExist = new CartInfo();
            cartInfoExist.setSkuId(skuId);
            cartInfoExist.setCartPrice(productFeignClient.getSkuPrice(skuId));
            cartInfoExist.setSkuPrice(productFeignClient.getSkuPrice(skuId));
            cartInfoExist.setSkuNum(skuNum);
            cartInfoExist.setUserId(userId);
            cartInfoExist.setImgUrl(skuInfo.getSkuDefaultImg());
            cartInfoExist.setSkuName(skuInfo.getSkuName());
            cartInfoExist.setCreateTime(new Date());
            cartInfoExist.setUpdateTime(new Date());

        }
        //  修改完成之后，要写入缓存！
        this.redisTemplate.opsForHash().put(cartKey, skuId.toString(), cartInfoExist);
    }

    @Override
    public List<CartInfo> getCartList(String userId, String userTempId) {
        //  声明未登录购物车集合
        List<CartInfo> noLoginCartInfoList = new ArrayList<>();
        //  判断：未登录购物车数据！
        if (!StringUtils.isEmpty(userTempId)) {
            //  查询临时购物车集合数据！
            //  获取临时购物车key
            String cartKey = this.getCartKey(userTempId);
            //  hget key field; 不能！ hvals key
            //  cartInfoList = this.redisTemplate.opsForHash().values(cartKey);
            noLoginCartInfoList = this.redisTemplate.boundHashOps(cartKey).values();
        }

        //  判断这个集合是否为空！ 只有一个临时用户Id！
        if (!CollectionUtils.isEmpty(noLoginCartInfoList) && StringUtils.isEmpty(userId)) {
            //  排序：
            noLoginCartInfoList.sort((o1, o2) -> {
                return DateUtil.truncatedCompareTo(o2.getUpdateTime(), o1.getUpdateTime(), Calendar.SECOND);
            });
            //  返回未登录购物车集合数据！
            return noLoginCartInfoList;
        }

        //  ----------------------------以下是登录情况----------------------------------------------------
         /*
        demo:
            登录：  1
                17  1
                18  1

            未登录： 11111
                17  1
                18  1
                19  2

             合并：
                17  2
                18  2
                19  2
         */


        if (!StringUtils.isEmpty(userId)) {
            //  查询登录购物车集合数据！
            //  获取登录购物车key
            String cartKey = this.getCartKey(userId);

            //  根据key 来获取数据：BoundHashOperations<H, HK, HV> hset key field value;
            BoundHashOperations<String, String, CartInfo> boundHashOperations = this.redisTemplate.boundHashOps(cartKey);

            //  noLoginCartInfoList 不为空才能合并！
            //  第一种方式双重for 循环！
            //            if (!CollectionUtils.isEmpty(noLoginCartInfoList)){
            //                for (CartInfo cartInfoNoLogin : noLoginCartInfoList) {
            //                    for (CartInfo cartInfoLogin : boundHashOperations.values()) {
            //                        if (cartInfoLogin.getSkuId().intValue()==cartInfoNoLogin.getSkuId().intValue()){
            //                            //  数量相加 ，更新updateTime！ 放入缓存！
            //                        }else {
            //                            //  直接放入缓存！
            //                        }
            //                    }
            //                }
            //            }

            //  声明一个登录的购物车集合数据
            List<CartInfo> LoginCartInfoList = null;
            //  第二种方案： 未登录购物车数据不为空！
            if (!CollectionUtils.isEmpty(noLoginCartInfoList)) {
                //  循环遍历这个未登录购物车集合数据
                //  未登录集合数据中是否包含已登录集合数据！
                noLoginCartInfoList.stream().forEach(cartInfoNoLogin -> {
                    //  hget key filed;
                    //                    CartInfo cartInfo = boundHashOperations.get(cartInfoNoLogin.getSkuId().toString());
                    //                    if(noLoginCartInfoList.contains(cartInfo)){
                    //
                    //                    }
                    //  这个登录购物车集合数据中是否包含skuId
                    if (boundHashOperations.hasKey(cartInfoNoLogin.getSkuId().toString())) {
                        //  数量相加： 17 ,18
                        CartInfo cartInfoLogin = boundHashOperations.get(cartInfoNoLogin.getSkuId().toString());
                        //  设置数量
                        cartInfoLogin.setSkuNum(cartInfoLogin.getSkuNum() + cartInfoNoLogin.getSkuNum());
                        //  设置更新时间
                        cartInfoLogin.setUpdateTime(new Date());

                        //  判断选中状态！
                        if (cartInfoNoLogin.getIsChecked().intValue()==1 && cartInfoLogin.getIsChecked().intValue()==0){
                            cartInfoLogin.setIsChecked(1);
                        }

                        //  放入redis！
                        boundHashOperations.put(cartInfoLogin.getSkuId().toString(), cartInfoLogin);
                    } else {
                        //  未登录：直接放入缓存！ 19
                        cartInfoNoLogin.setUserId(userId);
                        cartInfoNoLogin.setCreateTime(new Date());
                        cartInfoNoLogin.setUpdateTime(new Date());
                        boundHashOperations.put(cartInfoNoLogin.getSkuId().toString(),cartInfoNoLogin);
                    }
                });
            }

            //  删除未登录购物车：
            this.redisTemplate.delete(this.getCartKey(userTempId));
            //  获取到合并之后的所有数据：
            LoginCartInfoList = boundHashOperations.values();

            //  排序：
            if (!CollectionUtils.isEmpty(LoginCartInfoList)) {
                //  排序：
                LoginCartInfoList.sort((o1, o2) -> {
                    return DateUtil.truncatedCompareTo(o2.getUpdateTime(), o1.getUpdateTime(), Calendar.SECOND);
                });
                //  返回未登录购物车集合数据！
                return LoginCartInfoList;
            }
        }

        //  返回数据
        return new ArrayList<>();
    }

    @Override
    public void checkCart(Long skuId, String userId, Integer isChecked) {
        //  获取到购物车数据：
        String cartKey = this.getCartKey(userId);

        //  获取对应的数据：
        CartInfo cartInfo = (CartInfo) this.redisTemplate.opsForHash().get(cartKey, skuId.toString());
        //  Boolean flag = this.redisTemplate.opsForHash().hasKey(cartKey, skuId.toString());
        //  判断
        if(cartInfo!=null){
            cartInfo.setIsChecked(isChecked);
            this.redisTemplate.opsForHash().put(cartKey,skuId.toString(),cartInfo);
        }
    }

    @Override
    public void deleteCart(Long skuId, String userId) {
        //  获取到购物车集合列表！
        String cartKey = this.getCartKey(userId);
        //  获取到集合对应的数据并删除！ hdel key field
        this.redisTemplate.opsForHash().delete(cartKey, skuId.toString());
    }

    @Override
    public List<CartInfo> getCartInfoList(String userId) {
        //  获取购物车key
        String cartKey = this.getCartKey(userId);

        //  取redis 中的数据
        List<CartInfo> cartInfoList = this.redisTemplate.opsForHash().values(cartKey);
        //  is_checked = 1;  Stream 流： 只是对数据进行操作，并不会将结果返回！
        List<CartInfo> cartInfoCheckedList = cartInfoList.stream().filter((cartInfo) -> {
            //  为了保证用户在查看购物车列表时，商品价格是最新数据！
            cartInfo.setSkuPrice(this.productFeignClient.getSkuPrice(cartInfo.getSkuId()));
            //  过滤数据！
            return cartInfo.getIsChecked().intValue() == 1;
        }).collect(Collectors.toList());

        //  返回数据！
        return cartInfoCheckedList;
    }

    private String getCartKey(String userId) {
        return RedisConst.USER_KEY_PREFIX + userId + RedisConst.USER_CART_KEY_SUFFIX;
    }
}
